package com.um.springboot.starter.utils;

import lombok.extern.slf4j.Slf4j;

import javax.imageio.ImageIO;
import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;

@Slf4j
public class ImageUtil {

	private File file = null; // 文件对象 
	 private String inputDir; // 输入图路径
	 private String outputDir; // 输出图路径
	 private String inputFileName; // 输入图文件名
	 private String outputFileName; // 输出图文件名
	 private int outputWidth = 100; // 默认输出图片宽
	 private int outputHeight = 100; // 默认输出图片高
	 private boolean proportion = true; // 是否等比缩放标记(默认为等比缩放)
	 
	 public ImageUtil() { // 初始化变量
		 inputDir = ""; 
		 outputDir = ""; 
		 inputFileName = ""; 
		 outputFileName = ""; 
		 outputWidth = 100; 
		 outputHeight = 100; 
	 } 
	 public void setInputDir(String inputDir) { 
		 this.inputDir = inputDir; 
	 } 
	 public void setOutputDir(String outputDir) { 
		 this.outputDir = outputDir; 
	 } 
	 public void setInputFileName(String inputFileName) { 
		 this.inputFileName = inputFileName;
	 } 
	 public void setOutputFileName(String outputFileName) { 
		 this.outputFileName = outputFileName; 
	 } 
	 public void setOutputWidth(int outputWidth) {
		 this.outputWidth = outputWidth; 
	 } 
	 public void setOutputHeight(int outputHeight) { 
		 this.outputHeight = outputHeight; 
	 } 
	 public void setWidthAndHeight(int width, int height) { 
		 this.outputWidth = width;
		 this.outputHeight = height; 
	 } 

	 /* 
	  * 获得图片大小 
	  * 传入参数 String path ：图片路径 
	  */ 
	 public long getPicSize(String path) { 
		 file = new File(path); 
		 return file.length(); 
	 }

	 // 图片处理 
	 public String compressPic() { 
		 try { 
			 //获得源文件 
			 file = new File(inputDir +"/"+ inputFileName); 
			 if (!file.exists()) { 
				 return ""; 
			 } 
			 Image img = ImageIO.read(file); 
			 // 判断图片格式是否正确 
			 if (img.getWidth(null) == -1) {
				 return "no"; 
			 } else { 
				 int newWidth; int newHeight; 
				 // 判断是否是等比缩放 
				 if (this.proportion == true) { 
					 // 为等比缩放计算输出的图片宽度及高度 
					 double rate1 = ((double) img.getWidth(null)) / (double) outputWidth + 0.1; 
					 double rate2 = ((double) img.getHeight(null)) / (double) outputHeight + 0.1; 
					 // 根据缩放比率大的进行缩放控制 
					 double rate = rate1 > rate2 ? rate1 : rate2; 
					 newWidth = (int) (((double) img.getWidth(null)) / rate); 
					 newHeight = (int) (((double) img.getHeight(null)) / rate); 
				 } else { 
					 newWidth = outputWidth;//img.getWidth(null); // 输出的图片宽度 
					 newHeight = outputHeight;//img.getHeight(null); // 输出的图片高度 
				 } 
			 	BufferedImage bufferImage = new BufferedImage((int) newWidth, (int) newHeight, 2); 

			 	/*
				 * Image.SCALE_SMOOTH 的缩略算法 生成缩略图片的平滑度的
				 * 优先级比速度高 生成的图片质量比较好 但速度慢
				 */ 
			 	Graphics2D graphics = (Graphics2D)bufferImage.getGraphics();
			 	graphics.drawImage(img.getScaledInstance(newWidth, newHeight, Image.SCALE_SMOOTH), 0, 0,null);
			 	ImageIO.write(bufferImage, "png", new File(outputDir +"/"+ outputFileName));  
			 } 
		 } catch (IOException ex) { 
			 log.error("", ex); 
		 } 
		 return "ok"; 
	} 
	public String compressPic (String inputDir, String outputDir, String inputFileName, String outputFileName) { 
		// 输入图路径 
		this.inputDir = inputDir; 
		// 输出图路径 
		this.outputDir = outputDir; 
		// 输入图文件名 
		this.inputFileName = inputFileName; 
		// 输出图文件名
		this.outputFileName = outputFileName; 
		return compressPic(); 
	} 
	public String compressPic(String inputDir, String outputDir, String inputFileName, String outputFileName, int width, int height, boolean gp) { 
		// 输入图路径 
		this.inputDir = inputDir; 
		// 输出图路径 
		this.outputDir = outputDir; 
		// 输入图文件名 
		this.inputFileName = inputFileName; 
		// 输出图文件名 
		this.outputFileName = outputFileName; 
		// 设置图片长宽
		setWidthAndHeight(width, height); 
		// 是否是等比缩放 标记 
		this.proportion = gp; 
		return compressPic(); 
	} 

	
	/**
	 * 合并多张图片 Merge all pics in one ############# # pic1 # ############# # pic2 #
	 * ############# # pic3 # #############
	 * 
	 * @param pics
	 * @param dst_pic
	 * @return
	 */
	public static boolean merge(List<String> pics, String dst_pic, String type) {
		int len = pics.size();
		if (len < 1) {
			return false;
		}
		String  ROOT = "";//flex.messaging.FlexContext.getServletContext().getRealPath("/");	
		File[] src = new File[len];
		BufferedImage[] images = new BufferedImage[len];
		int[][] ImageArrays = new int[len][];
		for (int i = 0; i < len; i++) {
			try {
				src[i] = new File(ROOT+pics.get(i));
				images[i] = ImageIO.read(src[i]);
			} catch (Exception e) {
				log.error("", e);
				return false;
			}
			int width = images[i].getWidth();
			int height = images[i].getHeight();
			ImageArrays[i] = new int[width * height];// 从图片中读取RGB
			ImageArrays[i] = images[i].getRGB(0, 0, width, height,
					ImageArrays[i], 0, width);
		}
		int size = images.length;
		int dst_height = 0,dst_width = 0;
		if(size==1){
			dst_height = 125;
			dst_width = 125;
		}else if(size<5){
			dst_height = 245;
			dst_width = 245;
		}else{
			dst_height = 365;
			dst_width = 365;
		}
		// 生成新图片
		try {
			BufferedImage ImageNew = new BufferedImage(dst_width,
					dst_height, BufferedImage.TYPE_INT_RGB);
			Graphics2D g2 = (Graphics2D)ImageNew.getGraphics();      
//	        g2.setBackground(Color.LIGHT_GRAY); 
			g2.setBackground(Color.LIGHT_GRAY); 
	        g2.clearRect(0, 0, dst_width, dst_height);  
			int width_i = 5,height_i = 5;	
			int width = 0,height = 0;
			switch(size){
			case 1:			
				width = images[0].getWidth();
				height = images[0].getHeight();
				ImageNew.setRGB(width_i, height_i, width-5, height-5,
						ImageArrays[0], 0, width);
				break;
			case 2:
				for (int i = 0; i < 2; i++) {
					width = images[i].getWidth();
					height = images[i].getHeight();
					ImageNew.setRGB(width_i, height_i+(dst_height-height-5)/2, width-5, height-5,
							ImageArrays[i], 0, width);
					
					width_i += images[i].getWidth();
				}
				break;
			case 3:
				for (int i = 0; i < 3; i++) {
					width = images[i].getWidth();
					height = images[i].getHeight();
					if(i==0){
						ImageNew.setRGB(width_i+(dst_width-width)/2, height_i, width-5, height-5,
								ImageArrays[i], 0, width);
					}else{
						ImageNew.setRGB(width_i, height_i, width-5, height-5,
								ImageArrays[i], 0, width);	
					}
					if(i%2==0){
						height_i += images[i].getHeight();
					}else{
						width_i += images[i].getWidth();
					}
				}			
				break;
			case 4:
				for (int i = 0; i < 4; i++) {
					width = images[i].getWidth();
					height = images[i].getHeight();
					ImageNew.setRGB(width_i, height_i, width-5, height-5,
							ImageArrays[i], 0, width);
					if(i%2==0){
						width_i += images[i].getWidth();
					}else{
						width_i = 5;
						height_i += images[i].getHeight();
					}
				}
				break;
			case 5:
				for (int i = 0; i < 5; i++) {
					width = images[i].getWidth();
					height = images[i].getHeight();
					if(i==0){
						ImageNew.setRGB(width_i+(dst_width-width*2-5)/2, height_i+(dst_height-height*2-5)/2, width-5, height-5,
								ImageArrays[i], 0, width);
					}if(i==1){
						ImageNew.setRGB(width_i+(dst_width-width*2-5)/2+width, height_i+(dst_height-height*2-5)/2, width-5, height-5,
								ImageArrays[i], 0, width);
					}else{
						ImageNew.setRGB(width_i, height_i+(dst_height-height*2-5)/2+height, width-5, height-5,
								ImageArrays[i], 0, width);							
					}
					if(i%3!=0)
						width_i += images[i].getWidth();
				}
				break;
			case 6:
				for (int i = 0; i < 6; i++) {
					width = images[i].getWidth();
					height = images[i].getHeight();
					if(i<3){
						height_i=(dst_height-height*2)/2;
					}else{
						height_i=(dst_height-height*2)/2+height;
					}
					ImageNew.setRGB(width_i, height_i, width-5, height-5,
							ImageArrays[i], 0, width);
					if((i+1)%3!=0){
						width_i += images[i].getWidth();
					}else{
						width_i = 5;
					}					
				}
				break;
			case 7:
				for (int i = 0; i < 7; i++) {
					width = images[i].getWidth();
					height = images[i].getHeight();
					if(i==0){
						ImageNew.setRGB(width_i+(dst_width-width-5)/2, height_i+(dst_height-height*3-5)/2, width-5, height-5,
								ImageArrays[i], 0, width);
					}else{
						if(i<4){
							height_i=(dst_height-height*2);
						}else{
							height_i=(dst_height-height*2)+height;
						}
						ImageNew.setRGB(width_i, height_i, width-5, height-5,
								ImageArrays[i], 0, width);
						if((i+1)%4!=0){
							width_i += images[i].getWidth();
						}else{
							width_i = 5;
						}											
					}				
				}
				break;
			case 8:
				for (int i = 0; i < 8; i++) {
					width = images[i].getWidth();
					height = images[i].getHeight();
					if(i==0){
						ImageNew.setRGB(width_i+(dst_width-width*2-5)/2, height_i+(dst_height-height*3-5)/2, width-5, height-5,
								ImageArrays[i], 0, width);
					}else if(i==1){
						ImageNew.setRGB(width_i+(dst_width-width*2-5)/2+width, height_i+(dst_height-height*3-5)/2, width-5, height-5,
								ImageArrays[i], 0, width);
					}else{
						if(i<5){
							height_i=(dst_height-height*2);
						}else{
							height_i=(dst_height-height*2)+height;
						}
						ImageNew.setRGB(width_i, height_i, width-5, height-5,
								ImageArrays[i], 0, width);
						if((i+1)%5!=0){
							width_i += images[i].getWidth();
						}else{
							width_i = 5;
						}											
					}
				}
				break;
			case 9:
				for (int i = 0; i < 9; i++) {
					width = images[i].getWidth();
					height = images[i].getHeight();
					ImageNew.setRGB(width_i, height_i, width-5, height-5,
							ImageArrays[i], 0, width);
					if((i+1)%3!=0){
						width_i += images[i].getWidth();
					}else{
						width_i = 5;
						height_i+=height;
					}				
				}
				break;
			}			
			File outFile = new File(ROOT+dst_pic);
			ImageIO.write(ImageNew, type, outFile);// 写图片
			FileUtil.setThumbIcon(ROOT+dst_pic,120,120);//生成缩略图
			return true;
		} catch (Exception e) {
			log.error("", e);
			return false;
		}
	}

	/**
	 *  图片裁剪通用接口
	 *  @param src 源图像路径
	 *  @param dest 裁剪后图像路径
	 *  @param x 裁剪的图像左上角横坐标
	 *  @param y  裁剪的图像左上角纵坐标
	 *  @param w  裁剪的图像的宽
	 *  @param h  裁剪的图像的高
	 *  @throws IOException
	 **/
	public static void cutImage(String src, String dest, int x, int y, int w, int h, String imageType) throws IOException {
		if(imageType.equals("")){
			imageType = "jpg";
		}
		Iterator iterator = ImageIO.getImageReadersByFormatName(imageType);
		ImageReader reader = (ImageReader) iterator.next();
		InputStream in = new FileInputStream(src);
		ImageInputStream iis = ImageIO.createImageInputStream(in);
		reader.setInput(iis, true);
		ImageReadParam param = reader.getDefaultReadParam();
		Rectangle rect = new Rectangle(formartCoordinate(x), formartCoordinate(y), formartCoordinate(w), formartCoordinate(h));
		param.setSourceRegion(rect);
		BufferedImage bi = reader.read(0, param);
		ImageIO.write(bi, imageType, new File(dest));

		iis.close();
		in.close();
	}

	/**
	 * 获取图片宽度
	 * @param file  图片文件
	 * @return 宽度
	 */
	public static int getImgWidth(File file) {
		InputStream is = null;
		BufferedImage src = null;
		int ret = -1;
		try {
			is = new FileInputStream(file);
			src = ImageIO.read(is);
			ret = src.getWidth(null); // 得到源图宽
			is.close();
		} catch (Exception e) {
			log.error("", e);
		}
		return ret;
	}


	/**
	 * 获取图片高度
	 * @param file  图片文件
	 * @return 高度
	 */
	public static int getImgHeight(File file) {
		InputStream is = null;
		BufferedImage src = null;
		int ret = -1;
		try {
			is = new FileInputStream(file);
			src = ImageIO.read(is);
			ret = src.getHeight(null); // 得到源图高
			is.close();
		} catch (Exception e) {
			log.error("", e);
		}
		return ret;
	}

	/**
	 * 格式化坐标
	 * @param coordinate
	 * @return
	 */
	public static int formartCoordinate(int coordinate){
		return coordinate <= 0 ? 0 : coordinate;
	}
	
}
